﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using FPP.Models;
using FPP.Controllers;
using System.Net;
using System.IO;

namespace FPP.Utilities
{
    public class WikiUtil
    {
        public void UpdateWiki()
        {
            UpdateWiki(new List<int>());
        }
        public void UpdateWiki(string wikiUrl)
        {
            var updateIds = new List<int>();
            UpdateWiki(updateIds, wikiUrl);
        }

        public void UpdateWiki(int updateId)
        { 
            var updateIds = new List<int>();
            updateIds.Add(updateId);
            UpdateWiki(updateIds);
        }
        public void UpdateWiki(List<int> updateIds)
        {
            UpdateWiki(updateIds, string.Empty);
        }
        public void UpdateWiki(List<int> updateIds, string wikiUrl)
        {

            var context = new fppEntities(DataAccess.ffpCString);

            using (context)
            {
                context.Connection.Open();

                //a specific wiki link has been requested to be updated
                //If a specific link has been requested, update it and get out.
                if (!(string.IsNullOrEmpty(wikiUrl)))
                {
                    updateIds.AddRange(context.WikiLinks.Where(q => q.Link == wikiUrl).ToList().Select(link => link.Id));
                    ParseLinks(context, updateIds);
                    context.SaveChanges();
                    return;
                }
                //if there is no image for the link, most likely new.
                foreach (WikiLink link in context.WikiLinks.Where(q => q.ImageUrl == null).ToList())
                {
                    updateIds.Add(link.Id);
                }

                //if the url has been checked in the last 15 days then dont process
                var updateDate = DateTime.Now.AddDays(-15);
                foreach (WikiLink link in context.WikiLinks.Where(q => q.modDateTime != null).ToList())
                {
                    if (DateTime.Parse(link.modDateTime) > updateDate) continue;
                    updateIds.Add(link.Id);
                }

                ParseLinks(context, updateIds);

                context.SaveChanges();
            }
        }

        private void ParseLinks(fppEntities context, List<int> updateIds )
        {
                foreach (int updateId in updateIds)
                {
                    WikiLink link = context.WikiLinks.Single(q => q.Id == updateId);

                    try
                    {
                        var wikiPage = DownloadWebPage(link.Link);
                        link.DOB = GetDOB(wikiPage);
                        link.ImageUrl = GetImageUrl(wikiPage);
                        link.modDateTime = DateTime.Now.ToShortDateString();
                        link.DisplayName = GetDisplayName(wikiPage);
                        link.DOD = GetDOD(wikiPage);
                    }
                    catch
                    { }
                }

        }

        private string GetDisplayName(string wikiPage)
        {
            int dispNameClassStart = wikiPage.Contains("class=\"fn") ? wikiPage.IndexOf("class=\"firstHeading") : wikiPage.IndexOf("class=\"fn");
            string dispNameClass = wikiPage.Substring(dispNameClassStart, 300);
            int dispNameStart = dispNameClass.IndexOf(">") + 1;
            string dispName = dispNameClass.Substring(dispNameStart, 100);
            int dispNameEnd = dispName.IndexOf("<");
            return dispName.Substring(0, dispNameEnd);
        }

        private string GetDOB(string wikiPage)
        {
            int bDayStart = wikiPage.IndexOf("bday");
            return wikiPage.Substring(bDayStart + 6, 10);
        }

        private string GetDOD(string wikiPage)
        {
            try
            {
                int dDayStart = wikiPage.IndexOf("dday");
                return wikiPage.Substring(dDayStart + 16, 10);
            }
            catch
            {
                return null;
            }
        }

        private string GetImageUrl(string wikiPage)
        {
            try
            {
                int vCardStart = wikiPage.IndexOf("vcard");
                int maxLength = wikiPage.Length - vCardStart;
                string vCard = wikiPage.Substring(vCardStart, maxLength - 10);

                //Looking for the start of the next img src after the vcard
                int imgStart = vCard.IndexOf("src");
                maxLength = vCard.Length - imgStart;
                string imgStrip = vCard.Substring(imgStart + 5, maxLength - 10);

                 //Looking for the end of the vCard
                int vcardEnd = vCard.IndexOf("table");
                //If the table ends before an image was found. Then use default image.
                if (vcardEnd < imgStart)
                    return "http://www.famouspeoplepool.com/_assets/images/hollywood-star.jpg";

                int imgEnd = imgStrip.IndexOf("\"");
                return imgStrip.Substring(0, imgEnd);

           }
            catch
            {
                return "";
            }
        }
        /// <summary>
        /// Returns the content of a given web adress as string.
        /// </summary>
        /// <param name="Url">URL of the webpage</param>
        /// <returns>Website content</returns>
        private string DownloadWebPage(string Url)
        {
            // Open a connection
            HttpWebRequest WebRequestObject = (HttpWebRequest)HttpWebRequest.Create(Url);

            // You can also specify additional header values like 
            // the user agent or the referer:
            WebRequestObject.UserAgent = ".NET Framework/4.0";
            WebRequestObject.Referer = "http://www.FamousPeoplePool.com/";

            // Request response:
            WebResponse Response = WebRequestObject.GetResponse();

            // Open data stream:
            Stream WebStream = Response.GetResponseStream();

            // Create reader object:
            StreamReader Reader = new StreamReader(WebStream);

            // Read the entire stream content:
            string PageContent = Reader.ReadToEnd();

            // Cleanup
            Reader.Close();
            WebStream.Close();
            Response.Close();

            return PageContent;
        }

    }
}